#include "windowswindow.h"
#include "defines.h"
#include "../../resource.h"
#include "version.h"
#include <stdio.h>
#include "resources/resourcewindow.h"

namespace gunsmith
{
bool CWindowsWindow::m_bRunning = false;

CWindowsWindow::CWindowsWindow(UINT iWidth, UINT iHeight)
{
	m_hWnd		 = NULL;
	m_iWidth	 = iWidth;
	m_iHeight	 = iHeight;

	PreInit();
	Init();

	if(Create())
	{
		m_bRunning = true;

		CreateWindowResource();
		ShowWindow(m_hWnd, 1);
	}
	else
	{
		MessageBox(GetActiveWindow(), ERRMSG_CANT_CREATE_WINDOW, ERRCAP_CANT_CREATE_WINDOW, MB_OK | MB_ICONERROR);
		m_bRunning = false;
		return;
	}
}

CWindowsWindow::~CWindowsWindow()
{
	m_pResMngr->FreeResources();
	m_pResMngr->Release();
}

/*!	\brief		Creates the windows window.
	\return		bool
	\remarks	
	\sa			*/
bool CWindowsWindow::Create()
{
	m_hInstance = GetModuleHandle(0);

	// WINDOW CLASS
	WNDCLASS wc;
	ZeroMemory(&wc, sizeof(wc));	
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= &WndProc;
	wc.hInstance		= m_hInstance;
	wc.hbrBackground	= (HBRUSH)(COLOR_WINDOW);
	wc.lpszClassName	= "WindowClass";
	wc.hIcon			= LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_GSICON));
	RegisterClass(&wc);

	// GET DESKTOP EXTENTS
	RECT rc; GetWindowRect(GetDesktopWindow(), &rc);

	// construct last revision and date text for use in window caption
	char caption_string[128];
	sprintf_s(caption_string, 128, "GunSmith v0.01.%u - %s", g_iNumRevision, g_cLastChangedDate);

	// CREATE WINDOW
	m_hWnd = CreateWindow(wc.lpszClassName, caption_string, WS_OVERLAPPEDWINDOW,
						 (rc.right-m_iWidth)/2, (rc.bottom-m_iHeight)/2, m_iWidth, m_iHeight,
						 GetDesktopWindow(), NULL, m_hInstance, NULL);

	return m_hWnd != NULL;
}

/*!	\brief		The window proc handles incomming window messages.
	\param		hWnd				Window handle.
	\param		iMessage			Message ID.
	\param		wParam
	\param		lParam
	\return		LRESULT CALLBACK
	\remarks	
	\sa			*/
LRESULT CALLBACK CWindowsWindow::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	switch (iMessage)
	{
		//case WM_KEYDOWN:
		case WM_QUIT:
		case WM_DESTROY:
			PostQuitMessage(0);
			DestroyWindow(hWnd);
			m_bRunning = false;
			break;
		default:
			return DefWindowProc(hWnd, iMessage, wParam, lParam);
	}
	return 0;
}

/*!	\brief		The main message loop wich keeps the application running. Also provides the app with delta time via QPC.
	\return		void
	\remarks	
	\sa			*/
void CWindowsWindow::MessageLoop()
{
	MSG msg;
	__int64 iStart, iEnd, iFreq;
	QueryPerformanceCounter((LARGE_INTEGER*)&iStart);
	QueryPerformanceFrequency((LARGE_INTEGER*)&iFreq);

	while(m_bRunning)
	{
		if(PeekMessage(&msg, m_hWnd, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			QueryPerformanceCounter((LARGE_INTEGER*)&iEnd);
			Render(((float)(iEnd-iStart))/iFreq);
			iStart = iEnd;
		}
	}
}

/*!	\brief		Function that needs to be implemented by inheriting classes to output something to screen.
	\param		p_fDelta	Delta time.
	\return		void
	\remarks	
	\sa			*/
void CWindowsWindow::Render(float p_fDelta)
{
}

/*!	\brief		Things that you need to do even befor Init().
	\return		void
	\remarks	
	\sa			*/
void CWindowsWindow::PreInit()
{
}

/*!	\brief		The best place to put initialization code.
	\return		void
	\remarks	
	\sa			*/
void CWindowsWindow::Init()
{
	// Get resource manager
	m_pResMngr = CResourceManager::GetInstance();
}

/*!	\brief		
	\return		void
	\remarks	
	\sa			*/
void CWindowsWindow::CreateWindowResource()
{
	TDisplayWindowInfo pWindowInfo;
	pWindowInfo.hWnd			= m_hWnd;
	pWindowInfo.iColorDepth		= 32;
	pWindowInfo.iWidth			= m_iWidth;
	pWindowInfo.iHeight			= m_iHeight;
	pWindowInfo.iRefreshRate	= 0;
	pWindowInfo.pRunning		= &m_bRunning;
	
	m_pResMngr->CreateResource<CResourceWindow>(RID_DISPLAY_WINDOW, (void*)&pWindowInfo);
}
};